package city.spring.modules.system.model;

import city.spring.modules.system.entity.UserEntity;
import city.spring.utils.RoleUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 用户详细信息。提供给 Spring Security 程序使用的客户端信息对象
 *
 * @author HouKunLin
 * @date 2019/12/8 0008 3:27
 */
@Data
@EqualsAndHashCode
public class UserDetailsDTO implements UserDetails, Serializable {
    /**
     * 用户名。实际上为用户ID，保证用户信息的一致性，这样用户使用多种登录方式多次登录的时候，实际上都是同一个用户名（用户ID）
     */
    private String username;
    /**
     * 用户的密码信息
     */
    private String password;
    /**
     * 权限列表
     */
    private Collection<? extends GrantedAuthority> authorities;
    /**
     * 帐户未过期
     */
    private Boolean isAccountNonExpired;
    /**
     * 帐户未锁定
     */
    private Boolean isAccountNonLocked;
    /**
     * 凭证未过期
     */
    private Boolean isCredentialsNonExpired;
    /**
     * 启用
     */
    private Boolean isEnabled;
    /**
     * 登录时使用的标识符（用户名、邮箱、手机号）
     */
    private String loginUseIdentifier;

    public UserDetailsDTO(UserEntity entity) {
        this.username = entity.getId();
        this.password = entity.getPassword();
        setAuthorities(entity.getAllAuthorities());
        this.isAccountNonExpired = entity.getIsAccountNonExpired();
        this.isAccountNonLocked = entity.getIsAccountNonLocked();
        this.isCredentialsNonExpired = entity.getIsCredentialsNonExpired();
        this.isEnabled = entity.getIsEnabled();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Collection<GrantedAuthority> authorities) {
        this.authorities = new ArrayList<>(authorities);
    }

    public void setAuthorities(Set<String> values) {
        // 默认角色，每个用户都拥有的角色
        String defaultRole = RoleUtils.getAuthorityWithDefaultPrefix("GUEST");
        if (!values.contains(defaultRole)) {
            values = new LinkedHashSet<>(values);
            values.add(defaultRole);
        }
        setAuthorities(AuthorityUtils.createAuthorityList(values.toArray(new String[0])));
    }

    /**
     * 把当前用户的用户ID当做Security框架的用户名，因此在通过用户名获取用户信息的时候，需要把用户名当做id来进行一次处理
     */
    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return isAccountNonExpired != null && isAccountNonExpired;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return isAccountNonLocked != null && isAccountNonLocked;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return isCredentialsNonExpired != null && isCredentialsNonExpired;
    }

    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return isEnabled != null && isEnabled;
    }
}
